home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / plnk081.zip / pilot-link.0.8.1 / pi-csd.c.orig < prev    next >
Text File  |  1997-08-07  |  9KB  |  357 lines

  1. /* pi-csd.c: Connection Service Daemon, required for accepting logons via NetSync(tm)
  2.  *
  3.  * Copyright (c) 1997, Kenneth Albanowski
  4.  *
  5.  * This is free software, licensed under the GNU Public License V2.
  6.  * See the file COPYING for details.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include "pi-source.h"
  14. #include "pi-socket.h"
  15. #include "pi-dlp.h"
  16. #include "pi-serial.h"
  17. #include "pi-slp.h"
  18. #include <signal.h>
  19.  
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23. #include <net/if.h>
  24. #include <arpa/inet.h>
  25. #include <netdb.h>
  26.  
  27. char hostname[130];
  28. struct in_addr address, netmask;
  29.  
  30. void Help(char *argv[])
  31. {
  32.   fprintf(stderr,"usage:%s [options]\n",argv[0]);
  33.   fprintf(stderr,"\n      <-h hostname> Name of host, used for verification");
  34.   if (strlen(hostname))
  35.   fprintf(stderr,"\n                   (defaults to '%s')", hostname);
  36.   else
  37.   fprintf(stderr,"\n                   (no default)");  
  38.   fprintf(stderr,"\n      <-a address> IP address of host");
  39.   if (address.s_addr)
  40.   fprintf(stderr,"\n                   (defaults to '%s')", inet_ntoa(address));
  41.   else
  42.   fprintf(stderr,"\n                   (no default)");  
  43.   fprintf(stderr,"\n      <-s address> Subnet mask of IP address");
  44.   if (netmask.s_addr)
  45.   fprintf(stderr,"\n                   (defaults to '%s')", inet_ntoa(netmask));
  46.   else
  47.   fprintf(stderr,"\n                   (no default)");  
  48.   fprintf(stderr,"\n      <-q> Quiet: turn off status messages\n");
  49.   fprintf(stderr,"\nNote: Currently the subnet mask is not used by %s.\n", argv[0]);
  50.   exit(0);
  51. }
  52.  
  53. #ifdef HAVE_SA_LEN
  54. #ifndef max
  55. #define max(a,b) ((a) > (b) ? (a) : (b))
  56. #endif
  57. #define ifreq_size(i) max(sizeof(struct ifreq),\
  58.      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
  59. #else
  60. #define ifreq_size(i) sizeof(struct ifreq)
  61. #endif /* HAVE_SA_LEN*/
  62.  
  63.  
  64. /* What, me worry? */     
  65. #ifndef IFF_POINTOPOINT
  66. # ifdef IFF_POINTTOPOINT
  67. #  define IFF_POINTOPOINT IFF_POINTTOPOINT
  68. # endif
  69. #endif
  70.  
  71.  
  72. /* While this function is useful in pi-csd, it is intended also to
  73.    be a demonstration of the proper (or improper, if I'm unlucky) techniques
  74.    to retrieve networking information.*/
  75.    
  76. void fetch_host(char * hostname, int hostlen, struct in_addr *address, struct in_addr * mask)
  77. {
  78.   int s, n, i;
  79.   struct ifconf ifc;
  80.   struct ifreq * ifr, ifreqaddr, ifreqmask;
  81.   struct hostent * hent;
  82.   
  83. #ifdef HAVE_GETHOSTNAME
  84.   /* Get host name the easy way */
  85.   
  86.   gethostname(hostname, hostlen);
  87. #else
  88. # ifdef HAVE_UNAME
  89.   struct utsname uts;
  90.   
  91.   if (uname(&uts)==0) {
  92.     strncpy(hostname, uts.nodename, hostlen-1);
  93.     hostname[hostlen-1] = '\0';
  94.   }
  95. # endif /*def HAVE_UNAME*/
  96. #endif /*def HAVE_GETHOSTNAME*/
  97.  
  98.   /* Get host address through DNS */
  99.   hent = gethostbyname(hostname);
  100.   
  101.   if (hent) {
  102.     while(*hent->h_addr_list) {
  103.       struct in_addr haddr;
  104.       memcpy(&haddr, *(hent->h_addr_list++), sizeof(haddr));
  105.       if (haddr.s_addr != inet_addr("127.0.0.1"))
  106.           memcpy(address, &haddr, sizeof(haddr));
  107.     }
  108.   }
  109.  
  110. #if defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS) 
  111.   s = socket(AF_INET, SOCK_DGRAM, 0);
  112.  
  113.   if (s<0)
  114.     return;
  115.     
  116.   ifc.ifc_buf = calloc(1024, 1);
  117.   ifc.ifc_len = 1024;
  118.   
  119.   if (ioctl(s, SIOCGIFCONF, (char*)&ifc)<0)
  120.     goto done;
  121.   
  122.   n = ifc.ifc_len;
  123.   for (i=0; i<n; i+=ifreq_size(*ifr)) {
  124.     struct sockaddr_in * a;
  125.     struct sockaddr_in * b;
  126.     ifr = (struct ifreq*)((caddr_t) ifc.ifc_buf+i);
  127.     a = (struct sockaddr_in*)&ifr->ifr_addr;
  128.     strncpy(ifreqaddr.ifr_name, ifr->ifr_name, sizeof(ifreqaddr.ifr_name));
  129.     strncpy(ifreqmask.ifr_name, ifr->ifr_name, sizeof(ifreqmask.ifr_name));
  130.     
  131.     if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreqaddr) < 0)
  132.       continue;
  133.  
  134.     /* Reject loopback device */
  135. #ifdef IFF_LOOPBACK
  136.     if (ifreqaddr.ifr_flags & IFF_LOOPBACK)
  137.       continue;
  138. #endif /*def IFF_LOOPBACK*/
  139.  
  140. #ifdef IFF_UP
  141.     /* Reject down devices */
  142.     if (!(ifreqaddr.ifr_flags & IFF_UP))
  143.       continue;
  144. #endif /*def IFF_UP*/
  145.       
  146.     if (ifr->ifr_addr.sa_family != AF_INET)
  147.       continue;
  148.  
  149.     /* If it is a point-to-point device, use the dest address */
  150. #if defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR)
  151.     if (ifreqaddr.ifr_flags & IFF_POINTOPOINT) {
  152.       if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreqaddr) < 0)
  153.         break;
  154.  
  155.       a = (struct sockaddr_in*)&ifreqaddr.ifr_dstaddr;
  156.     
  157.       if (address->s_addr == 0) {
  158.         memcpy(address, &a->sin_addr, sizeof(struct in_addr));
  159.       }
  160.     } else
  161. #endif /*defined(IFF_POINTOPOINT) && defined(SIOCGIFDSTADDR)*/
  162.     /* If it isn't a point-to-point device, use the address */
  163. #ifdef SIOCGIFADDR
  164.     {
  165.       if (ioctl(s, SIOCGIFADDR, (char *)&ifreqaddr) < 0)
  166.         break;
  167.  
  168.       a = (struct sockaddr_in*)&ifreqaddr.ifr_addr;
  169.  
  170.       if (address->s_addr == 0) {
  171.         memcpy(address, &a->sin_addr, sizeof(struct in_addr));
  172.       }
  173.     }
  174. #endif /*def SIOCGIFADDR*/    
  175.     /* OK, we've got an address */
  176.  
  177.     /* Compare netmask against the current address and see if it seems to match. */
  178. #ifdef SIOCGIFNETMASK    
  179.     if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreqmask) < 0)
  180.       break;
  181.  
  182. /*
  183.  * NetBSD probably falls into the same camp - need to check
  184.  */
  185. #if defined (__FreeBSD__) || defined (__NetBSD__)
  186.     b = (struct sockaddr_in*)&ifreqmask.ifr_addr;
  187. #else
  188.     b = (struct sockaddr_in*)&ifreqmask.ifr_netmask;
  189. #endif
  190.  
  191.     if ((mask->s_addr == 0) && (address->s_addr != 0)) {
  192.       if ((b->sin_addr.s_addr & a->sin_addr.s_addr) == (b->sin_addr.s_addr & address->s_addr)) {
  193.         memcpy(mask, &b->sin_addr, sizeof(struct in_addr));
  194.         
  195.         /* OK, we've got a netmask */
  196.         
  197.         break;
  198.       }
  199.     }
  200. #endif /*def SIOCGIFNETMASK*/
  201.  
  202.   }
  203.   
  204. done:
  205.   free(ifc.ifc_buf);
  206.   close(s);
  207. #endif /*defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)*/
  208. }
  209.  
  210. void main(int argc, char*argv[]) {
  211.     int sockfd;
  212.     struct sockaddr_in serv_addr, cli_addr;
  213.     int clilen;
  214.     char mesg[1026];
  215.     fd_set rset;
  216.     int n;
  217.     struct in_addr raddress;
  218.  
  219.   char * progname;
  220.   extern char* optarg;
  221.   extern int optind;
  222.  
  223.   struct hostent * hent;
  224.   int quiet=0;
  225.   
  226.   progname = argv[0];
  227.  
  228.   memset(&address, 0, sizeof(address));
  229.   memset(&netmask, 0, sizeof(netmask));
  230.   hostname[0] = 0;
  231.   
  232.   fetch_host(hostname, 128, &address, &netmask);
  233.   
  234.   while ((n = getopt(argc, argv, "h:s:a:q")) != EOF) {
  235.     switch (n) {
  236.       case 'h':
  237.         strcpy(hostname, optarg);
  238.         break;
  239.       case 'a':
  240.         if (!inet_aton(optarg, &address))
  241.           if ((hent = gethostbyname(optarg)))
  242.           memcpy(&address.s_addr, hent->h_addr, sizeof(address));
  243.         else {
  244.           fprintf(stderr, "Invalid address '%s'\n\n", optarg);
  245.           Help(argv);
  246.         }
  247.         break;
  248.       case 's':
  249.         if (!inet_aton(optarg, &netmask))
  250.           Help(argv);
  251.         break;
  252.       case 'q':
  253.         quiet = 1;
  254.         break;
  255.       case 'H': case '?': default:
  256.         Help(argv);
  257.     }
  258.   }
  259.   
  260.   if ((address.s_addr == 0) || (strlen(hostname)==0))
  261.     Help(argv); /* cannot execute without address and hostname */
  262.     
  263.   sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  264.   if (sockfd <0 ) {
  265.     perror("Unable to get socket");
  266.     exit(1);
  267.   }
  268.  
  269.   memset(&serv_addr, 0, sizeof(serv_addr));
  270.   serv_addr.sin_family = AF_INET;
  271.   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  272.   serv_addr.sin_port = htons(14237);
  273.  
  274.   if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))< 0) {
  275.     perror("Unable to bind socket");
  276.     exit(1);
  277.   }
  278.   
  279.   if (!quiet) {
  280.     fprintf(stderr, "%s(%d): Connection Service Daemon for PalmPilot(tm) active.\n",
  281.                 progname, getpid());
  282.     fprintf(stderr, "%s(%d): Accepting connection requests for '%s' at %s",
  283.             progname, getpid(),
  284.             hostname,
  285.             inet_ntoa(address)
  286.            );
  287.     fprintf(stderr, " with mask %s.\n",
  288.             inet_ntoa(netmask)
  289.            );
  290.   }
  291.   for (;;) {
  292.     clilen = sizeof(cli_addr);
  293.     FD_ZERO(&rset);
  294.     FD_SET(sockfd, &rset);
  295.     if (select(sockfd+1, &rset, 0, 0, 0)<0) {
  296.       perror("select failure");
  297.       exit(1);
  298.     }
  299.     n = recvfrom(sockfd, mesg, 1024, 0, (struct sockaddr*)&cli_addr, &clilen);
  300.  
  301.     if (n<0) {
  302.       continue;
  303.     }
  304.  
  305.     mesg[n] = 0;
  306.  
  307.     if (!quiet) {
  308.       hent = gethostbyaddr((char*)&cli_addr.sin_addr.s_addr,4,AF_INET);
  309.       memcpy(&raddress, &cli_addr.sin_addr.s_addr, 4);
  310.  
  311.       fprintf(stderr, "%s(%d): Connection from %s[%s], ",
  312.               progname,
  313.               getpid(),
  314.               hent ? hent->h_name : "", 
  315.               inet_ntoa(raddress));
  316.     }
  317.  
  318.     if (get_short(mesg) != 0xFADE)
  319.       goto invalid;
  320.  
  321.     if ((get_byte(mesg+2) == 0x01) && (n>12)) {
  322.       struct in_addr ip, mask;
  323.       char * name = mesg+12;
  324.       memcpy(&ip, mesg+4, 4);
  325.       memcpy(&mask, mesg+8, 4);
  326.  
  327.       if (!quiet) {
  328.         fprintf(stderr, "req '%s', %s",
  329.                 name, inet_ntoa(ip));
  330.                 fprintf(stderr, ", %s", inet_ntoa(mask));
  331.       }
  332.  
  333.       if (strcmp(hostname, name)==0) {
  334.         if (!quiet)
  335.           fprintf(stderr, " = accept.\n");
  336.  
  337.         set_byte(mesg+2, 0x02);
  338.         memcpy(mesg+4, &address, 4); /* address is already in motorola byte order */
  339.         n = sendto(sockfd, mesg, n, 0, (struct sockaddr*)&cli_addr, clilen);
  340.         if (n < 0) {
  341.           perror("sendto error");
  342.         }
  343.         continue;
  344.       }
  345.       if (!quiet)
  346.         fprintf(stderr, " = reject.\n");
  347.       continue;
  348.     }
  349.  
  350.     invalid:
  351.     if (!quiet)
  352.       fprintf(stderr, "invalid packet of %d bytes:\n", n);
  353.     dumpdata(mesg, n);
  354.   }
  355. }
  356.  
  357.